<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Wallet\Ctl;

use Srv\Apps\Apis\Common\DefCtl\DefBalanceCategoryCtl;
use Srv\Apps\Apis\Common\IdxCtl\IdxIp;
use Srv\Apps\Apis\User\Ctl\UserCtl;
use Srv\Apps\Proto\DTO\Wallet\WalletBalanceListDTO;
use Srv\Apps\Proto\DTO\Wallet\WalletBalanceRecordListDTO;
use Srv\Apps\Proto\Enum\WalletBalanceTypeEnum;
use Srv\Apps\Proto\Enum\YesOrNoEnum;
use Srv\Apps\Proto\VO\User\UserInfoBasicVO;
use Srv\Apps\Proto\VO\Wallet\WalletBalanceListVO;
use Srv\Apps\Proto\VO\Wallet\WalletBalanceRecordListVO;
use Srv\Apps\Proto\VO\Wallet\WalletBalanceRecordVO;
use Srv\Apps\Proto\VO\Wallet\WalletBalanceVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class WalletCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write
    public const WALLET_BILL_TYPE_IN        = 1;        // 收入
    public const WALLET_BILL_TYPE_OUT       = 2;        // 支出

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return WalletBalanceListVO|null
     * getWalletBalanceList
     */
    public function getWalletBalanceList(Page $Page, array $whereData): ?WalletBalanceListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE 1 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case WalletBalanceListDTO::_uswbId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'uswb_id='. intval($val);
                    break;
                case WalletBalanceListDTO::_userId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='.intval($val);
                    break;
                case WalletBalanceListDTO::_dbtcId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'dbtc_id='.intval($val);
                    break;
                case WalletBalanceListDTO::_status:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'uswb_status='.intval($val);
                    break;
                case WalletBalanceListDTO::_idNum:
                    if(strlen($val) > 10 && is_numeric($val)){
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='.intval($val);
                    }else{
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN(SELECT user_id FROM '.$this->DbAuto->getTableNameAll('user_info').' WHERE usi_idnum LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\' AND usi_delete=0)';
                    }
                    break;
            }
        }
        $isFail             = false;
        $sql                = 'SELECT SQL_CALC_FOUND_ROWS uswb_id, user_id, dbtc_id, uswb_balance, uswb_balance_use, uswb_balance_all, uswb_status, uswb_sign_num, uswb_version, uswb_create_time, uswb_update_time FROM '.$this->DbAuto->getTableNameAll('wallet_balance').$whereString.' ORDER BY uswb_id DESC '.$limitString;
        $list               = $this->DbAuto->getData($sql, $isFail);
        $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $WalletBalanceVOList            = [];
        if(CommArray::isForeach($list)){
            $userIdList                 = array_map('intval', array_column($list, 'user_id'));
            $UserInfoBasicVOList        = UserCtl::tag()->getUserInfoBasicBatch($userIdList);
            foreach($list as $item){
                $uswbIdItem             = intval($item['uswb_id']);
                if($uswbIdItem < 1) continue;
                $WalletBalanceVO        = $this->getWalletBalanceVO($item);
                if(!($WalletBalanceVO instanceof WalletBalanceVO)) continue;
                $userIdItem             = intval($item['user_id']);
                $UserInfoBasicVO        = $UserInfoBasicVOList[$userIdItem]??null;
                if($UserInfoBasicVO instanceof UserInfoBasicVO) $WalletBalanceVO->setUserInfoBasic($UserInfoBasicVO);
                $WalletBalanceVOList[]  = $WalletBalanceVO;
            }
        }
        $WalletBalanceListVO            = new WalletBalanceListVO();
        $WalletBalanceListVO->setList($WalletBalanceVOList);
        $WalletBalanceListVO->setPage($Page->getPageVO($totalNum));
        return $WalletBalanceListVO;
    }

    /**
     * @param array $walletBalance
     * @return WalletBalanceVO|null
     * getWalletBalanceVO
     */
    public function getWalletBalanceVO(array $walletBalance): ?WalletBalanceVO
    {
        $uswbId             = intval($walletBalance['uswb_id']??0);
        if($uswbId < 1) return null;
        $WalletBalanceVO    = new WalletBalanceVO();
        $WalletBalanceVO->setUswbId($uswbId);
        $dbtcId             = intval($walletBalance['dbtc_id']);
        if($dbtcId > 0){
            $category       = DefBalanceCategoryCtl::tag()->getExtStrById($dbtcId, DefBalanceCategoryCtl::EXT_NAME);
            $WalletBalanceVO->setCategory($category);
        }
        $WalletBalanceVO->setBalance(intval($walletBalance['uswb_balance']));
        $WalletBalanceVO->setBalanceUse(intval($walletBalance['uswb_balance_use']));
        $WalletBalanceVO->setBalanceAll(intval($walletBalance['uswb_balance_all']));
        $WalletBalanceVO->setStatus(YesOrNoEnum::parseValue($walletBalance['uswb_status']));
        $WalletBalanceVO->setSignNum($walletBalance['uswb_sign_num']);
        $WalletBalanceVO->setVersion(intval($walletBalance['uswb_version']));
        $WalletBalanceVO->setCreateTime(intval($walletBalance['uswb_create_time']));
        $WalletBalanceVO->setUpdateTime(intval($walletBalance['uswb_update_time']));
        return $WalletBalanceVO;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return WalletBalanceRecordListVO|null
     * getWalletBalanceRecordList
     */
    public function getWalletBalanceRecordList(Page $Page, array $whereData): ?WalletBalanceRecordListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE 1 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case WalletBalanceRecordListDTO::_uwbrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'uwbr_id='. intval($val);
                    break;
                case WalletBalanceRecordListDTO::_uswbId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'uswb_id='. intval($val);
                    break;
                case WalletBalanceRecordListDTO::_userId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='.intval($val);
                    break;
                case WalletBalanceRecordListDTO::_dbtcId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'dbtc_id='.intval($val);
                    break;
                case WalletBalanceRecordListDTO::_type:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'uwbr_type='.intval($val);
                    break;
                case WalletBalanceRecordListDTO::_idNum:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN(SELECT user_id FROM '.$this->DbAuto->getTableNameAll('user_info').' WHERE usi_idnum LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\' AND usi_delete=0)';
                    break;
            }
        }
        $isFail             = false;
        $sql                = 'SELECT SQL_CALC_FOUND_ROWS uwbr_id, uswb_id, user_id, dbtc_id, uwbr_type, uwbr_balance_before, uwbr_balance, uwbr_balance_after, uwbr_remark_data, uwbr_ip, dup_id, uwbr_create_time FROM '.$this->DbAuto->getTableNameAll('wallet_balance_record').$whereString.' ORDER BY uwbr_id DESC '.$limitString;
        $list               = $this->DbAuto->getData($sql, $isFail);
        $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $WalletBalanceRecordVOList  = [];
        if(CommArray::isForeach($list)){
            $userIdList             = array_map('intval', array_column($list, 'user_id'));
            $UserInfoBasicVOList    = UserCtl::tag()->getUserInfoBasicBatch($userIdList);
            foreach($list as $item){
                $uwbrIdItem                     = intval($item['uwbr_id']);
                if($uwbrIdItem < 1) continue;
                $WalletBalanceRecordVO          = $this->getWalletBalanceRecordVO($item);
                if(!($WalletBalanceRecordVO instanceof WalletBalanceRecordVO)) continue;
                $userIdItem                     = intval($item['user_id']);
                $UserInfoBasicVO                = $UserInfoBasicVOList[$userIdItem]??null;
                if($UserInfoBasicVO instanceof UserInfoBasicVO) $WalletBalanceRecordVO->setUserInfoBasic($UserInfoBasicVO);
                $WalletBalanceRecordVOList[]    = $WalletBalanceRecordVO;
            }
        }
        $WalletBalanceRecordListVO  = new WalletBalanceRecordListVO();
        $WalletBalanceRecordListVO->setList($WalletBalanceRecordVOList);
        $WalletBalanceRecordListVO->setPage($Page->getPageVO($totalNum));
        return $WalletBalanceRecordListVO;
    }

    /**
     * @param array $walletBalanceRecord
     * @return WalletBalanceRecordVO|null
     * getWalletBalanceRecordVO
     */
    public function getWalletBalanceRecordVO(array $walletBalanceRecord): ?WalletBalanceRecordVO
    {
        $uwbrId                 = intval($walletBalanceRecord['uwbr_id']??0);
        if($uwbrId < 1) return null;
        $WalletBalanceRecordVO  = new WalletBalanceRecordVO();
        $WalletBalanceRecordVO->setUwbrId($uwbrId);
        $WalletBalanceRecordVO->setUswbId(intval($walletBalanceRecord['uswb_id']));
        $dbtcId                 = intval($walletBalanceRecord['dbtc_id']);
        if($dbtcId > 0){
            $category           = DefBalanceCategoryCtl::tag()->getExtStrById($dbtcId, DefBalanceCategoryCtl::EXT_NAME);
            $WalletBalanceRecordVO->setCategory($category);
        }
        $WalletBalanceRecordVO->setType(WalletBalanceTypeEnum::parseValue($walletBalanceRecord['uwbr_type']));
        $WalletBalanceRecordVO->setBalanceBefore(intval($walletBalanceRecord['uwbr_balance_before']));
        $WalletBalanceRecordVO->setBalance(intval($walletBalanceRecord['uwbr_balance']));
        $WalletBalanceRecordVO->setBalanceAfter(intval($walletBalanceRecord['uwbr_balance_after']));
        $WalletBalanceRecordVO->setRemarkData($walletBalanceRecord['uwbr_remark_data']);
        $ipStr                  = IdxIp::tag()->getIpStrByIntStr($walletBalanceRecord['uwbr_ip']);
        $WalletBalanceRecordVO->setIpStr($ipStr);
        $WalletBalanceRecordVO->setCreateTime(intval($walletBalanceRecord['uwbr_create_time']));
        return $WalletBalanceRecordVO;
    }


    /**
     * @param int $userId
     * @param int $dbtcId
     * @param int $balance
     * @param int $status
     * @param int $version
     * @param int $createTime
     * @param int $updateTime
     * @return int
     * genWalletSignNum
     */
    private function genWalletSignNum(int $userId, int $dbtcId, int $balance, int $status, int $version, int $createTime, int $updateTime):int
    {
        return crc32(sha1(''.$userId.$dbtcId.$balance.$status.$version.$createTime.$updateTime));
    }

    /**
     * @param int $userId
     * @param int $dbtcId
     * @return int
     * initWalletForCategory
     */
    private function initWalletForCategory(int $userId, int $dbtcId):int
    {
        if($userId < 1 || $dbtcId < 1) return 0;
        $uswbId     = $this->DbAuto->getDataInt('SELECT uswb_id FROM '.$this->DbAuto->getTableNameAll('wallet_balance').' WHERE user_id='.$userId.' AND dbtc_id='.$dbtcId, 'uswb_id');
        if($uswbId > 0) return $uswbId;
        $currTime   = CommTime::getTimeStamp();
        $signNum    = $this->genWalletSignNum($userId, $dbtcId, 0, 0, 1, $currTime, $currTime);
        return $this->DbAuto->getDataId('INSERT INTO '.$this->DbAuto->getTableNameAll('wallet_balance').' SET user_id='.$userId.', dbtc_id='.$dbtcId.', uswb_balance=0, uswb_balance_use=0, uswb_balance_all=0, uswb_status=0, uswb_sign_num='.$signNum.', uswb_version=1, uswb_create_time='.$currTime.', uswb_update_time='.$currTime);
    }

    /**
     * @param int $dbtcId
     * @param bool $optType
     * @param int $userId
     * @param int $amount
     * @param int $dbbzId
     * @param array $bizData
     * @param array $balanceData
     * @param bool $bizShow
     * @param int $uwbrId
     * @param int $wbsrId
     * @return bool
     * setWalletBalanceForType
     */
    private function setWalletBalanceForType(int $dbtcId, bool $optType, int $userId, int $amount, int $dbbzId, array $bizData, array $balanceData, bool $bizShow, int &$uwbrId, int &$wbsrId):bool
    {
        $uwbrId             = 0;
        $wbsrId             = 0;
        if($dbtcId < 1 || $userId < 1 || $amount < 1 || $dbbzId < 0) return false;
        $uswbId             = $this->initWalletForCategory($userId, $dbtcId);
        if($uswbId < 1) return false;
        $walletBalance      = $this->DbAuto->getDataOne('SELECT uswb_id, user_id, dbtc_id, uswb_balance, uswb_status, uswb_sign_num, uswb_version, uswb_create_time, uswb_update_time FROM '.$this->DbAuto->getTableNameAll('wallet_balance').' WHERE uswb_id='.$uswbId.' AND user_id='.$userId.' AND dbtc_id='.$dbtcId);
        if(!isset($walletBalance['uswb_id'])) return false;
        $balanceId          = intval($walletBalance['uswb_id']);
        $balanceStatus      = intval($walletBalance['uswb_status']);
        $balanceSignNum     = intval($walletBalance['uswb_sign_num']);
        $balanceVersion     = intval($walletBalance['uswb_version']);
        $dbtcIdBalance      = intval($walletBalance['dbtc_id']);
        if($balanceId < 1 || $balanceId !== $uswbId || $dbtcIdBalance < 1 || $dbtcIdBalance !== $dbtcId || $balanceStatus !== 0 || $balanceVersion < 1 || $balanceSignNum < 1) return false;
        $balanceOld         = intval($walletBalance['uswb_balance']);
        $balanceCreateTime  = intval($walletBalance['uswb_create_time']);
        $balanceUpdateTime  = intval($walletBalance['uswb_update_time']);
        $signNumOld         = $this->genWalletSignNum($userId, $dbtcId, $balanceOld, $balanceStatus, $balanceVersion, $balanceCreateTime, $balanceUpdateTime);
        if($signNumOld !== $balanceSignNum) return false;
        if($optType){
            $balanceNew     = $balanceOld + $amount;
        }else{
            $balanceNew     = $balanceOld - $amount;
        }
        if($balanceNew < 0) return false;
        $currTime           = CommTime::getTimeStamp();
        $versionNew         = $balanceVersion + 1;
        if($versionNew < 1) $versionNew = mt_rand(100000, 999999);
        $signNumNew         = $this->genWalletSignNum($userId, $dbtcId, $balanceNew, $balanceStatus, $versionNew, $balanceCreateTime, $currTime);
        if($optType){
            $sqlUpdate      = 'UPDATE '.$this->DbAuto->getTableNameAll('wallet_balance').' SET uswb_balance='.$balanceNew.', uswb_balance_all=uswb_balance_all+'.$amount.', uswb_sign_num='.$signNumNew.', uswb_version='.$versionNew.', uswb_update_time='.$currTime.' WHERE uswb_id='.$uswbId.' AND user_id='.$userId.' AND dbtc_id='.$dbtcId.' AND uswb_version='.$balanceVersion.' AND uswb_sign_num='.$signNumOld.' AND uswb_status=0';
        }else{
            $sqlUpdate      = 'UPDATE '.$this->DbAuto->getTableNameAll('wallet_balance').' SET uswb_balance='.$balanceNew.', uswb_balance_use=uswb_balance_use+'.$amount.', uswb_sign_num='.$signNumNew.', uswb_version='.$versionNew.', uswb_update_time='.$currTime.' WHERE uswb_id='.$uswbId.' AND user_id='.$userId.' AND dbtc_id='.$dbtcId.' AND uswb_version='.$balanceVersion.' AND uswb_sign_num='.$signNumOld.' AND uswb_status=0';
        }
        if($this->DbAuto->getDataNum($sqlUpdate) !== 1) return false;
        $optTypeNum         = $optType ? self::WALLET_BILL_TYPE_IN : self::WALLET_BILL_TYPE_OUT;
        $balanceData['__CRC32__'] = [$signNumOld, $signNumNew];
        $balanceDataJson= CommJson::encodeArray($balanceData);
        $uwbrId             = $this->DbAuto->getDataId('INSERT INTO '.$this->DbAuto->getTableNameAll('wallet_balance_record').' SET uswb_id='.$uswbId.', user_id='.$userId.', dbtc_id='.$dbtcId.', uwbr_type='.$optTypeNum.', uwbr_balance_before='.$balanceOld.', uwbr_balance='.$amount.', uwbr_balance_after='.$balanceNew.', uwbr_remark_data=\''.$this->DbAuto->getRealEscapeString($balanceDataJson).'\', uwbr_create_time='.$currTime);
        if($uwbrId < 1) return false;
        if($dbbzId > 0){
            $bizDataJson    = CommJson::encodeArray($bizData);
            $wbsrId         = $this->DbAuto->getDataId('INSERT INTO '.$this->DbAuto->getTableNameAll('wallet_bills_record').' SET uwbr_id='.$uwbrId.', user_id='.$userId.', dbtc_id='.$dbtcId.', wbsr_type='.$optTypeNum.', wbsr_balance='.$amount.', wbsr_show='.($bizShow?1:0).', dbbz_id='.$dbbzId.', wbsr_remark_data=\''.$this->DbAuto->getRealEscapeString($bizDataJson).'\', wbsr_create_time='.$currTime);
            if($wbsrId < 1) return false;
        }
        return true;
    }

    /**
     * @param int $userId
     * @param int $dbtcId
     * @param bool $status
     * @param bool $isExists
     * @return int
     * getWalletBalanceAmount
     */
    private function getWalletBalanceAmount(int $userId, int $dbtcId, bool &$status = false, bool &$isExists = false):int
    {
        $status             = false;
        $isExists           = false;
        if($userId < 1 || $dbtcId < 1) return 0;
        $walletBalance      = $this->DbAuto->getDataOne('SELECT uswb_balance, uswb_status FROM '.$this->DbAuto->getTableNameAll('wallet_balance').' WHERE user_id='.$userId.' AND dbtc_id='.$dbtcId);
        if(!isset($walletBalance['uswb_balance']) || !isset($walletBalance['uswb_status'])) return 0;
        $status             = intval($walletBalance['uswb_status']) === 0;
        $isExists           = true;
        return intval($walletBalance['uswb_balance']);
    }

    /**
     * @param int $userId
     * @param int $dbtcId
     * @return array
     * getWalletBalanceData
     */
    private function getWalletBalanceData(int $userId, int $dbtcId):array
    {
        if($userId < 1 || $dbtcId < 1) return [];
        $walletBalance      = $this->DbAuto->getDataOne('SELECT uswb_id, user_id, dbtc_id, uswb_balance, uswb_status, uswb_create_time FROM '.$this->DbAuto->getTableNameAll('wallet_balance').' WHERE user_id='.$userId.' AND dbtc_id='.$dbtcId);
        if(!isset($walletBalance['uswb_id'])) return [];
        return [
            'uswbId'        => intval($walletBalance['uswb_id']),
            'userId'        => intval($walletBalance['user_id']),
            'dbtcId'        => intval($walletBalance['dbtc_id']),
            'balance'       => intval($walletBalance['uswb_balance']),
            'status'        => intval($walletBalance['uswb_status']) === 0,
            'createTime'    => intval($walletBalance['uswb_create_time']),
        ];
    }

    /**
     * @param int $userId
     * @param bool $status
     * @param bool $isExists
     * @return int
     * getWalletBalanceAmountForCoin
     */
    public function getWalletBalanceAmountForCoin(int $userId, bool &$status = false, bool &$isExists = false):int
    {
        return $this->getWalletBalanceAmount($userId, DefBalanceCategoryCtl::tag()->getIdByKey(DefBalanceCategoryCtl::KEY_BALANCE_COIN), $status, $isExists);
    }

    /**
     * @param int $userId
     * @return array
     * getWalletBalanceDataForCoin
     */
    public function getWalletBalanceDataForCoin(int $userId):array
    {
        return $this->getWalletBalanceData($userId, DefBalanceCategoryCtl::tag()->getIdByKey(DefBalanceCategoryCtl::KEY_BALANCE_COIN));
    }

    /**
     * @param int $userId
     * @param int $amount
     * @param int $dbbzId
     * @param array $bizData
     * @param array $balanceData
     * @param bool $bizShow
     * @param int $billId
     * @param int $balanceId
     * @return bool
     * incWalletBalanceForCoin
     */
    public function incWalletBalanceForCoin(int $userId, int $amount, int $dbbzId, array $bizData, array $balanceData, bool $bizShow = true, int &$billId = 0, int &$balanceId = 0):bool
    {
        return $this->setWalletBalanceForType(DefBalanceCategoryCtl::tag()->getIdByKey(DefBalanceCategoryCtl::KEY_BALANCE_COIN), true, $userId, $amount, $dbbzId, $bizData, $balanceData, $bizShow, $balanceId, $billId);
    }

    /**
     * @param int $userId
     * @param int $amount
     * @param int $dbbzId
     * @param array $bizData
     * @param array $balanceData
     * @param bool $bizShow
     * @param int $billId
     * @param int $balanceId
     * @return bool
     * decWalletBalanceForCoin
     */
    public function decWalletBalanceForCoin(int $userId, int $amount, int $dbbzId, array $bizData, array $balanceData, bool $bizShow = true, int &$billId = 0, int &$balanceId = 0):bool
    {
        return $this->setWalletBalanceForType(DefBalanceCategoryCtl::tag()->getIdByKey(DefBalanceCategoryCtl::KEY_BALANCE_COIN), false, $userId, $amount, $dbbzId, $bizData, $balanceData, $bizShow, $balanceId, $billId);
    }

    /**
     * @param int $userId
     * @return int
     * getCoinGiveNum
     */
    public function getCoinGiveNum(int $userId):int
    {
        if($userId < 1) return 0;
        $currTime       = CommTime::getTimeStamp();
        $isFail         = false;
        $coinGive       = $this->DbAuto->getDataInt('SELECT SUM(cnge_curr_num) as num FROM '.$this->DbAuto->getTableNameAll('coin_give').' WHERE user_id='.$userId.' AND (cnge_start_expire=0 OR cnge_start_expire<'.$currTime.') AND (cnge_end_expire=0 OR cnge_end_expire>'.$currTime.') AND cnge_valid_status=1 AND cnge_delete=0 AND cnge_curr_num>0', 'num', $isFail);
        if($isFail) return 0;
        return $coinGive;
    }

    /**
     * @param array $userIdList
     * @return array
     * getCoinBalanceBatch
     */
    public function getCoinBalanceBatch(array $userIdList):array
    {
        if(count($userIdList) < 1) return [];
        $isFail         = false;
        $listData       = [];
        $dbtcId         = DefBalanceCategoryCtl::tag()->getIdByKey(DefBalanceCategoryCtl::KEY_BALANCE_COIN);
        $list           = $this->DbAuto->getData('SELECT user_id, SUM(uswb_balance) AS num FROM '.$this->DbAuto->getTableNameAll('wallet_balance').' WHERE user_id IN('.implode(',', $userIdList).') AND dbtc_id='.$dbtcId.' GROUP BY user_id', $isFail);
        if(!$isFail && CommArray::isForeach($list)) foreach ($list as $item){
            $userIdItem             = intval($item['user_id']??0);
            if($userIdItem < 1) continue;
            $listData[$userIdItem]  = intval($item['num']);
        }
        return $listData;
    }

    /**
     * @param array $userIdList
     * @return array
     * getCoinGiveNumBatch
     */
    public function getCoinGiveNumBatch(array $userIdList):array
    {
        if(count($userIdList) < 1) return [];
        $currTime       = CommTime::getTimeStamp();
        $isFail         = false;
        $listData       = [];
        $list           = $this->DbAuto->getData('SELECT user_id, SUM(cnge_curr_num) as num FROM '.$this->DbAuto->getTableNameAll('coin_give').' WHERE user_id IN('.implode(',', $userIdList).') AND (cnge_start_expire=0 OR cnge_start_expire<'.$currTime.') AND (cnge_end_expire=0 OR cnge_end_expire>'.$currTime.') AND cnge_valid_status=1 AND cnge_delete=0 AND cnge_curr_num>0 GROUP BY user_id', $isFail);
        if(!$isFail && CommArray::isForeach($list)) foreach ($list as $item){
            $userIdItem             = intval($item['user_id']??0);
            if($userIdItem < 1) continue;
            $listData[$userIdItem]  = intval($item['num']);
        }
        return $listData;
    }

    /**
     * @param int $userId
     * @return int
     * getBalanceAllNum
     */
    public function getBalanceAllNum(int $userId):int
    {
        if($userId < 1) return 0;
        $status         = false;
        $isExists       = false;
        $balanceNum     = $this->getWalletBalanceAmountForCoin($userId, $status, $isExists);
        $currTime       = CommTime::getTimeStamp();
        // 赠送的有效内的看点
        $coinGive       = $this->DbAuto->getDataInt('SELECT SUM(cnge_curr_num) as num FROM '.$this->DbAuto->getTableNameAll('coin_give').' WHERE user_id='.$userId.' AND (cnge_start_expire=0 OR cnge_start_expire<'.$currTime.') AND (cnge_end_expire=0 OR cnge_end_expire>'.$currTime.') AND cnge_valid_status=1 AND cnge_delete=0 AND cnge_curr_num>0', 'num');
        return $balanceNum + $coinGive;
    }

    /**
     * @param array $userIdList
     * @return array
     * getUserPayTotal
     */
    public function getUserPayTotal(array $userIdList):array
    {
        if(count($userIdList) < 1) return [];
        $isFail         = false;
        $listData       = [];
        $list           = $this->DbAuto->getData('SELECT user_id, SUM(porr_amount) AS num FROM '.$this->DbAuto->getTableNameAll('pay_order_record').' WHERE user_id IN('.implode(',', $userIdList).') AND porr_result=1 GROUP BY user_id', $isFail);
        if(!$isFail && CommArray::isForeach($list)) foreach ($list as $item){
            $userIdItem             = intval($item['user_id']??0);
            if($userIdItem < 1) continue;
            $listData[$userIdItem]  = intval($item['num']);
        }
        return $listData;
    }
}